
import Utility.ChatServer;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.logging.*;
import javax.swing.Timer;
import javax.swing.JComboBox;
import javax.swing.GroupLayout.Alignment;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.GroupLayout;
import javax.swing.DefaultComboBoxModel;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
import javax.swing.JButton;
import java.awt.Dimension;

/**
 *
 * @author Leenix
 */
public class ServerWindow extends javax.swing.JFrame {

    private static int timerInterval = 1000;
    private final String connectionsLblTitle = "Active Users: ";
    private static final Logger logger = Logger.getLogger("ChatServer");
    private final OutputStream ServerOutputStream = new ServerOutputStream();
    protected ChatServer server;

    /**
     * Creates new form PrivateChatServer
     */
    public ServerWindow() {
        server = new ChatServer();
        initComponents();
        
        // Initialise logging components.
        logger.setLevel(Level.FINER);
        Handler handler = new ServerStreamHandler(ServerOutputStream, new SimpleFormatter());
        handler.setLevel(Level.FINER);
        logger.addHandler(handler);

        // Display the IP Address of the server in the title bar.
        try {
            setTitle("JCU Message Server: " + InetAddress.getLocalHost().getHostAddress());
        } catch (UnknownHostException ex) {
            Logger.getLogger(ServerWindow.class.getName()).log(Level.SEVERE, null, ex);
        }

        Timer timer = new Timer(timerInterval, new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                connectionNumLbl.setText(connectionsLblTitle + server.getNumConnections());
            }
        });
        timer.start();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        portNumLbl = new javax.swing.JLabel();
        portNumField = new javax.swing.JTextField();
        startBtn = new javax.swing.JButton();
        stopBtn = new javax.swing.JButton();
        connectionNumLbl = new javax.swing.JLabel();
        newChatroomField = new javax.swing.JTextField();
        newChatroomBtn = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        statusArea = new javax.swing.JTextArea();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Private Message Server");
        setName("serverFrame");
        setPreferredSize(new Dimension(450, 300));
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosed(java.awt.event.WindowEvent evt) {
                formWindowClosed(evt);
            }
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        jPanel1.setPreferredSize(new java.awt.Dimension(500, 80));

        portNumLbl.setText("Listen Port: ");

        portNumField.setText("49222");

        startBtn.setText("Start");
        startBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                startBtnActionPerformed(evt);
            }
        });

        stopBtn.setText("Stop");
        stopBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                stopBtnActionPerformed(evt);
            }
        });

        connectionNumLbl.setText("Active Users: ");

        newChatroomBtn.setText("Create New Chatroom");
        newChatroomBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newChatroomBtnActionPerformed(evt);
            }
        });
        
        final JComboBox<Object> comboBox = new JComboBox<Object>();
        comboBox.setMaximumRowCount(9);
        comboBox.addItemListener(new ItemListener() {
        	public void itemStateChanged(ItemEvent arg0) {
        		logger.setLevel(Level.parse(comboBox.getSelectedItem().toString()));
        	}
        });
        comboBox.setModel(new DefaultComboBoxModel<Object>(new String[] {"OFF", "SEVERE", "WARNING", "INFO", "CONFIG", "FINE", "FINER", "FINEST", "ALL"}));
        comboBox.setSelectedIndex(3);
        
        JButton clearBtn = new JButton("C");
        clearBtn.setForeground(Color.RED);
        clearBtn.addActionListener(new ActionListener() {
        	public void actionPerformed(ActionEvent arg0) {
        		statusArea.setText("");
        		
        	}
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1Layout.setHorizontalGroup(
        	jPanel1Layout.createParallelGroup(Alignment.LEADING)
        		.addGroup(jPanel1Layout.createSequentialGroup()
        			.addContainerGap()
        			.addGroup(jPanel1Layout.createParallelGroup(Alignment.LEADING, false)
        				.addGroup(jPanel1Layout.createSequentialGroup()
        					.addComponent(portNumLbl)
        					.addPreferredGap(ComponentPlacement.RELATED)
        					.addComponent(portNumField, GroupLayout.PREFERRED_SIZE, 52, GroupLayout.PREFERRED_SIZE))
        				.addComponent(newChatroomField))
        			.addPreferredGap(ComponentPlacement.RELATED)
        			.addGroup(jPanel1Layout.createParallelGroup(Alignment.LEADING)
        				.addGroup(jPanel1Layout.createSequentialGroup()
        					.addComponent(startBtn)
        					.addPreferredGap(ComponentPlacement.RELATED)
        					.addComponent(stopBtn)
        					.addPreferredGap(ComponentPlacement.RELATED)
        					.addComponent(connectionNumLbl, GroupLayout.DEFAULT_SIZE, 97, Short.MAX_VALUE))
        				.addGroup(jPanel1Layout.createSequentialGroup()
        					.addComponent(newChatroomBtn)
        					.addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        					.addComponent(comboBox, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)))
        			.addGap(14)
        			.addComponent(clearBtn)
        			.addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
        	jPanel1Layout.createParallelGroup(Alignment.TRAILING)
        		.addGroup(jPanel1Layout.createSequentialGroup()
        			.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        			.addGroup(jPanel1Layout.createParallelGroup(Alignment.BASELINE)
        				.addComponent(portNumLbl)
        				.addComponent(portNumField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
        				.addComponent(startBtn)
        				.addComponent(stopBtn)
        				.addComponent(connectionNumLbl))
        			.addPreferredGap(ComponentPlacement.RELATED)
        			.addGroup(jPanel1Layout.createParallelGroup(Alignment.BASELINE)
        				.addComponent(newChatroomField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
        				.addComponent(newChatroomBtn)
        				.addComponent(comboBox, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
        				.addComponent(clearBtn))
        			.addGap(33))
        );
        jPanel1.setLayout(jPanel1Layout);

        getContentPane().add(jPanel1, java.awt.BorderLayout.PAGE_END);

        statusArea.setColumns(20);
        statusArea.setEditable(false);
        statusArea.setRows(5);
        jScrollPane1.setViewportView(statusArea);

        getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);

        pack();
    }// </editor-fold>

    /**
     * Starts the server utility for the Group Chat program and disables the
     * port number field from being changed.
     *
     * @param evt Button press
     */
    private void startBtnActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // Get port number and parse to an integer.
        int portNum = Integer.parseInt(portNumField.getText());
        server.setPortNumber(portNum);
        server.start();
        portNumField.setEditable(false);
        portNumField.setBackground(Color.LIGHT_GRAY);
    }                                        

    /**
     * Stops the server utility for the Group Chat program. Enables changing of
     * the port number field.
     *
     * @param evt Button press
     */
    private void stopBtnActionPerformed(java.awt.event.ActionEvent evt) {                                        
        server.purgeClients();
        
        //Wait for the shutdown message to be broadcast.
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            Logger.getLogger(ServerWindow.class.getName()).log(Level.SEVERE, null, ex);
        }
        server.stop();
        portNumField.setEditable(true);
        portNumField.setBackground(Color.WHITE);
    }                                       

    private void formWindowClosing(java.awt.event.WindowEvent evt) {                                   
        server.purgeClients();
    }                                  

    private void formWindowClosed(java.awt.event.WindowEvent evt) {                                  
        server.stop();
    }                                 

    private void newChatroomBtnActionPerformed(java.awt.event.ActionEvent evt) {
        server.createChatroom(newChatroomField.getText());
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(ServerWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(ServerWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(ServerWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(ServerWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new ServerWindow().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify
    private javax.swing.JLabel connectionNumLbl;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JButton newChatroomBtn;
    private javax.swing.JTextField newChatroomField;
    private javax.swing.JTextField portNumField;
    private javax.swing.JLabel portNumLbl;
    private javax.swing.JButton startBtn;
    private javax.swing.JTextArea statusArea;
    private javax.swing.JButton stopBtn;
    // End of variables declaration

    class ServerOutputStream extends OutputStream {

        @Override
        public void write(int b) throws IOException {
        }

        ;
        
        @Override
        public void write(byte[] b, int off, int len) {
            String s = new String(b, off, len);
            statusArea.insert(s, 0);
        }
    }

    class ServerStreamHandler extends StreamHandler {

        public ServerStreamHandler(OutputStream out, Formatter formatter) {
            super(out, formatter);
        }

        @Override
        public synchronized void publish(LogRecord record) {
            super.publish(record);
            flush();
        }
    }
}
